// Any is 魔鬼，要慎用、少用
const any_num: any = 100

// never 的特性是可以赋值给任何其他类型，但反过来不能被其他任何类型（包括 any 在内）赋值（即 never 是 bottom type）
{
    let never: never = (() => {
        throw new Error("never");
    })();
    let a: number = never
    let b: () => any = never
    let c: {} = never
}

// unknown
{
    let unknown: unknown
    // 不能将类型“unknown”分配给类型“number”
    // let a: number = unknown
    let a: number = 10
    let b = unknown = a
}

// void null undefined
{
    let thisIsAny: any;
    let thisIsNever: never;
    let thisIsUnknown: unknown;
    let thisIsVoid: void;
    let thisIsUndefined: undefined;
    let thisIsNull: null;
  
    thisIsAny = thisIsVoid; // ok
    thisIsUnknown = thisIsVoid; // ok
    thisIsVoid = thisIsAny; // ok
    thisIsVoid = thisIsNever; // ok
    thisIsVoid = thisIsUndefined; // ok
  
    thisIsAny = thisIsNull; // ok
    thisIsUnknown = thisIsNull; // ok
    thisIsAny = thisIsUndefined; // ok
    thisIsUnknown = thisIsUndefined; // ok
  
    thisIsNull = thisIsAny; // ok
    thisIsNull = thisIsNever; // ok
    thisIsUndefined = thisIsAny; // ok
    thisIsUndefined = thisIsNever; // ok
}

// enum
// 不能准确反映数值特性，慎用

// 泛型:泛型类型、泛型类
{
    let fun1 = <T>(p: T): 1 => 1
    let fun2 = <T>(p: T): number => 2
    fun2 = fun1 // ok
}

// 协变: 协变也就是说如果 Dog 是 Animal 的子类型，则 F(Dog) 是 F(Animal) 的子类型
{
    interface Animal {
        name: string
    }
    interface Dog extends Animal {
        woof: () => void
    }
    type isChild<Child, Parent> = Child extends Parent ? true : false
    type Covariance<T> = T
    // type isCovariant = true
    type isCovariant = isChild<Covariance<Dog>, Covariance<Animal>>
}

// 逆变: 逆变也就是说如果 Dog 是 Animal 的子类型，则 F(Dog) 是 F(Animal) 的父类型
{
    interface Animal {
        name: string
    }
    interface Dog extends Animal {
        woof: () => void
    }
    type isChild<Child, Parent> = Child extends Parent ? true : false
    type Contravariance<T> = (param: T) => void;
    // type isNotContravariance = false
    type isNotContravariance = isChild<Contravariance<Dog>, Contravariance<Animal>>; // false;
    // type isContravariance = true
    type isContravariance = isChild<Contravariance<Animal>, Contravariance<Dog>>; // true;

    const visitDog = (animal: Dog) => animal.woof()
    // 对象文字可以只指定已知属性，并且“miao”不在类型“Animal”中
    // let animals: Animal[] = [{ name: 'Cat', miao: () => void 0, }];
    // 类型“(animal: Dog) => void”的参数不能赋给类型“(value: Animal, index: number, array: Animal[]) => void”的参数。
    // 参数“animal”和“value” 的类型不兼容。
    // 类型 "Animal" 中缺少属性 "woof"，但类型 "Dog" 中需要该属性。ts(2345)
    // animals.forEach(visitDog);
}